1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.apache.tapestry5.ioc.internal.util;
16
17 import org.apache.tapestry5.func.F;
18 import org.apache.tapestry5.func.Mapper;
19 import org.apache.tapestry5.func.Predicate;
20 import org.apache.tapestry5.internal.plastic.PlasticInternalUtils;
21 import org.apache.tapestry5.ioc.*;
22 import org.apache.tapestry5.ioc.annotations.*;
23 import org.apache.tapestry5.ioc.def.*;
24 import org.apache.tapestry5.ioc.internal.ServiceDefImpl;
25 import org.apache.tapestry5.ioc.services.Coercion;
26 import org.apache.tapestry5.ioc.util.ExceptionUtils;
27 import org.apache.tapestry5.plastic.PlasticUtils;
28 import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
29 import org.slf4j.Logger;
30
31 import javax.annotation.PostConstruct;
32 import javax.inject.Named;
33
34 import java.io.Closeable;
35 import java.io.IOException;
36 import java.lang.annotation.Annotation;
37 import java.lang.annotation.Retention;
38 import java.lang.annotation.RetentionPolicy;
39 import java.lang.reflect.*;
40 import java.net.URL;
41 import java.util.*;
42 import java.util.concurrent.atomic.AtomicLong;
43 import java.util.regex.Matcher;
44 import java.util.regex.Pattern;
45
46
47
48
49 @SuppressWarnings("all")
50 public class InternalUtils
51 {
52
53
54
55 public static final boolean SERVICE_CLASS_RELOADING_ENABLED = Boolean.parseBoolean(System.getProperty(
56 IOCConstants.SERVICE_CLASS_RELOADING_ENABLED, "true"));
57
58
59
60
61
62
63
64
65
66
67
68
69 public static String asString(Method method, PlasticProxyFactory proxyFactory)
70 {
71 Location location = proxyFactory.getMethodLocation(method);
72
73 return location != null ? location.toString() : asString(method);
74 }
75
76
77
78
79
80
81
82
83 public static String asString(Method method)
84 {
85 return InternalCommonsUtils.asString(method);
86 }
87
88
89
90
91
92 public static int size(Object[] array)
93 {
94 return array == null ? 0 : array.length;
95 }
96
97 public static int size(Collection collection)
98 {
99 return collection == null ? 0 : collection.size();
100 }
101
102
103
104
105 public static String stripMemberName(String memberName)
106 {
107 return InternalCommonsUtils.stripMemberName(memberName);
108 }
109
110
111
112
113 public static List<String> toList(Enumeration e)
114 {
115 List<String> result = CollectionFactory.newList();
116
117 while (e.hasMoreElements())
118 {
119 String name = (String) e.nextElement();
120
121 result.add(name);
122 }
123
124 Collections.sort(result);
125
126 return result;
127 }
128
129
130
131
132
133
134
135
136
137
138
139 public static <T extends Annotation> T findAnnotation(Annotation[] annotations, Class<T> annotationClass)
140 {
141 for (Annotation a : annotations)
142 {
143 if (annotationClass.isInstance(a))
144 return annotationClass.cast(a);
145 }
146
147 return null;
148 }
149
150 private static ObjectCreator<Object> asObjectCreator(final Object fixedValue)
151 {
152 return new ObjectCreator<Object>()
153 {
154 @Override
155 public Object createObject()
156 {
157 return fixedValue;
158 }
159 };
160 }
161
162 private static ObjectCreator calculateInjection(final Class injectionType, Type genericType, final Annotation[] annotations,
163 final ObjectLocator locator, InjectionResources resources)
164 {
165 final AnnotationProvider provider = new AnnotationProvider()
166 {
167 @Override
168 public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
169 {
170 return findAnnotation(annotations, annotationClass);
171 }
172 };
173
174
175
176
177 InjectService is = provider.getAnnotation(InjectService.class);
178
179 if (is != null)
180 {
181 String serviceId = is.value();
182
183 return asObjectCreator(locator.getService(serviceId, injectionType));
184 }
185
186 Named named = provider.getAnnotation(Named.class);
187
188 if (named != null)
189 {
190 return asObjectCreator(locator.getService(named.value(), injectionType));
191 }
192
193
194
195
196 if (provider.getAnnotation(Inject.class) == null)
197 {
198 Object result = resources.findResource(injectionType, genericType);
199
200 if (result != null)
201 {
202 return asObjectCreator(result);
203 }
204 }
205
206
207
208
209
210 if (provider.getAnnotation(Autobuild.class) != null)
211 {
212 return new ObjectCreator()
213 {
214 @Override
215 public Object createObject()
216 {
217 return locator.getObject(injectionType, provider);
218 }
219 };
220 }
221
222
223
224
225 return asObjectCreator(locator.getObject(injectionType, provider));
226 }
227
228 public static ObjectCreator[] calculateParametersForMethod(Method method, ObjectLocator locator,
229 InjectionResources resources, OperationTracker tracker)
230 {
231
232 return calculateParameters(locator, resources, method.getParameterTypes(), method.getGenericParameterTypes(),
233 method.getParameterAnnotations(), tracker);
234 }
235
236 public static ObjectCreator[] calculateParameters(final ObjectLocator locator, final InjectionResources resources,
237 Class[] parameterTypes, final Type[] genericTypes, Annotation[][] parameterAnnotations,
238 OperationTracker tracker)
239 {
240 int parameterCount = parameterTypes.length;
241
242 ObjectCreator[] parameters = new ObjectCreator[parameterCount];
243
244 for (int i = 0; i < parameterCount; i++)
245 {
246 final Class type = parameterTypes[i];
247 final Type genericType = genericTypes[i];
248 final Annotation[] annotations = parameterAnnotations[i];
249
250 String description = String.format("Determining injection value for parameter #%d (%s)", i + 1,
251 PlasticUtils.toTypeName(type));
252
253 final Invokable<ObjectCreator> operation = new Invokable<ObjectCreator>()
254 {
255 @Override
256 public ObjectCreator invoke()
257 {
258 return calculateInjection(type, genericType, annotations, locator, resources);
259 }
260 };
261
262 parameters[i] = tracker.invoke(description, operation);
263 }
264
265 return parameters;
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281 public static void injectIntoFields(final Object object, final ObjectLocator locator,
282 final InjectionResources resources, OperationTracker tracker)
283 {
284 Class clazz = object.getClass();
285
286 while (clazz != Object.class)
287 {
288 Field[] fields = clazz.getDeclaredFields();
289
290 for (final Field f : fields)
291 {
292
293
294 int fieldModifiers = f.getModifiers();
295
296 if (Modifier.isStatic(fieldModifiers) || Modifier.isFinal(fieldModifiers))
297 continue;
298
299 final AnnotationProvider ap = new AnnotationProvider()
300 {
301 @Override
302 public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
303 {
304 return f.getAnnotation(annotationClass);
305 }
306 };
307
308 String description = String.format("Calculating possible injection value for field %s.%s (%s)",
309 clazz.getName(), f.getName(),
310 PlasticUtils.toTypeName(f.getType()));
311
312 tracker.run(description, new Runnable()
313 {
314 @Override
315 public void run()
316 {
317 final Class<?> fieldType = f.getType();
318
319 InjectService is = ap.getAnnotation(InjectService.class);
320 if (is != null)
321 {
322 inject(object, f, locator.getService(is.value(), fieldType));
323 return;
324 }
325
326 if (ap.getAnnotation(Inject.class) != null || ap.getAnnotation(InjectResource.class) != null)
327 {
328 Object value = resources.findResource(fieldType, f.getGenericType());
329
330 if (value != null)
331 {
332 inject(object, f, value);
333 return;
334 }
335
336 inject(object, f, locator.getObject(fieldType, ap));
337 return;
338 }
339
340 if (ap.getAnnotation(javax.inject.Inject.class) != null)
341 {
342 Named named = ap.getAnnotation(Named.class);
343
344 if (named == null)
345 {
346 Object value = resources.findResource(fieldType, f.getGenericType());
347
348 if (value != null)
349 {
350 inject(object, f, value);
351 return;
352 }
353
354 inject(object, f, locator.getObject(fieldType, ap));
355 } else
356 {
357 inject(object, f, locator.getService(named.value(), fieldType));
358 }
359
360 return;
361 }
362
363
364
365 }
366 });
367 }
368
369 clazz = clazz.getSuperclass();
370 }
371 }
372
373 private synchronized static void inject(Object target, Field field, Object value)
374 {
375 try
376 {
377 if (!field.isAccessible())
378 field.setAccessible(true);
379
380 field.set(target, value);
381
382
383 } catch (Exception ex)
384 {
385 throw new RuntimeException(String.format("Unable to set field '%s' of %s to %s: %s", field.getName(),
386 target, value, ExceptionUtils.toMessage(ex)));
387 }
388 }
389
390
391
392
393 public static String join(List elements)
394 {
395 return InternalCommonsUtils.join(elements);
396 }
397
398
399
400
401
402
403
404
405
406
407 public static String join(List elements, String separator)
408 {
409 return InternalCommonsUtils.join(elements, separator);
410 }
411
412
413
414
415
416
417
418 public static String joinSorted(Collection elements)
419 {
420 return InternalCommonsUtils.joinSorted(elements);
421 }
422
423
424
425
426
427 public static boolean isBlank(String input)
428 {
429 return InternalCommonsUtils.isBlank(input);
430 }
431
432
433
434
435
436 public static boolean isEmptyCollection(Object input)
437 {
438 if (input instanceof Collection)
439 {
440 return ((Collection) input).isEmpty();
441 }
442
443 return false;
444 }
445
446 public static boolean isNonBlank(String input)
447 {
448 return InternalCommonsUtils.isNonBlank(input);
449 }
450
451
452
453
454 public static String capitalize(String input)
455 {
456 return InternalCommonsUtils.capitalize(input);
457 }
458
459
460
461
462
463
464 public static Location locationOf(Object location)
465 {
466 return InternalCommonsUtils.locationOf(location);
467 }
468
469 public static <K, V> Set<K> keys(Map<K, V> map)
470 {
471 if (map == null)
472 return Collections.emptySet();
473
474 return map.keySet();
475 }
476
477
478
479
480
481
482
483
484
485
486
487
488 public static <K, V> V get(Map<K, V> map, K key)
489 {
490 if (map == null)
491 return null;
492
493 return map.get(key);
494 }
495
496
497
498
499 public static boolean isStatic(Method method)
500 {
501 return Modifier.isStatic(method.getModifiers());
502 }
503
504 public static <T> Iterator<T> reverseIterator(final List<T> list)
505 {
506 final ListIterator<T> normal = list.listIterator(list.size());
507
508 return new Iterator<T>()
509 {
510 @Override
511 public boolean hasNext()
512 {
513 return normal.hasPrevious();
514 }
515
516 @Override
517 public T next()
518 {
519 return normal.previous();
520 }
521
522 @Override
523 public void remove()
524 {
525 throw new UnsupportedOperationException();
526 }
527 };
528 }
529
530
531
532
533 public static boolean containsSymbols(String input)
534 {
535 return InternalCommonsUtils.containsSymbols(input);
536 }
537
538
539
540
541
542
543
544 public static String lastTerm(String input)
545 {
546 return InternalCommonsUtils.lastTerm(input);
547 }
548
549
550
551
552
553
554
555
556
557
558
559
560 public static Constructor findAutobuildConstructor(Class clazz)
561 {
562 Constructor[] constructors = clazz.getConstructors();
563
564 switch (constructors.length)
565 {
566 case 1:
567
568 return constructors[0];
569
570 case 0:
571
572 return null;
573
574 default:
575 break;
576 }
577
578 Constructor standardConstructor = findConstructorByAnnotation(constructors, Inject.class);
579 Constructor javaxConstructor = findConstructorByAnnotation(constructors, javax.inject.Inject.class);
580
581 if (standardConstructor != null && javaxConstructor != null)
582 throw new IllegalArgumentException(
583 String.format(
584 "Too many autobuild constructors found: use either @%s or @%s annotation to mark a single constructor for autobuilding.",
585 Inject.class.getName(), javax.inject.Inject.class.getName()));
586
587 if (standardConstructor != null)
588 {
589 return standardConstructor;
590 }
591
592 if (javaxConstructor != null)
593 {
594 return javaxConstructor;
595 }
596
597
598
599 Comparator<Constructor> comparator = new Comparator<Constructor>()
600 {
601 @Override
602 public int compare(Constructor o1, Constructor o2)
603 {
604 return o2.getParameterTypes().length - o1.getParameterTypes().length;
605 }
606 };
607
608 Arrays.sort(constructors, comparator);
609
610 return constructors[0];
611 }
612
613 private static <T extends Annotation> Constructor findConstructorByAnnotation(Constructor[] constructors,
614 Class<T> annotationClass)
615 {
616 for (Constructor c : constructors)
617 {
618 if (c.getAnnotation(annotationClass) != null)
619 return c;
620 }
621
622 return null;
623 }
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640 public static <K, V> void addToMapList(Map<K, List<V>> map, K key, V value)
641 {
642 InternalCommonsUtils.addToMapList(map, key, value);
643 }
644
645
646
647
648
649
650
651 public static void validateMarkerAnnotation(Class markerClass)
652 {
653 Retention policy = (Retention) markerClass.getAnnotation(Retention.class);
654
655 if (policy != null && policy.value() == RetentionPolicy.RUNTIME)
656 return;
657
658 throw new IllegalArgumentException(UtilMessages.badMarkerAnnotation(markerClass));
659 }
660
661 public static void validateMarkerAnnotations(Class[] markerClasses)
662 {
663 for (Class markerClass : markerClasses)
664 validateMarkerAnnotation(markerClass);
665 }
666
667 public static void close(Closeable stream)
668 {
669 if (stream != null)
670 try
671 {
672 stream.close();
673 } catch (IOException ex)
674 {
675
676 }
677 }
678
679
680
681
682
683
684
685
686
687
688 public static String toMessage(Throwable exception)
689 {
690 return ExceptionUtils.toMessage(exception);
691 }
692
693 public static void validateConstructorForAutobuild(Constructor constructor)
694 {
695 Class clazz = constructor.getDeclaringClass();
696
697 if (!Modifier.isPublic(clazz.getModifiers()))
698 throw new IllegalArgumentException(String.format(
699 "Class %s is not a public class and may not be autobuilt.", clazz.getName()));
700
701 if (!Modifier.isPublic(constructor.getModifiers()))
702 throw new IllegalArgumentException(
703 String.format(
704 "Constructor %s is not public and may not be used for autobuilding an instance of the class. "
705 + "You should make the constructor public, or mark an alternate public constructor with the @Inject annotation.",
706 constructor));
707 }
708
709
710
711
712 public static final Mapper<Class, AnnotationProvider> CLASS_TO_AP_MAPPER = new Mapper<Class, AnnotationProvider>()
713 {
714 @Override
715 public AnnotationProvider map(final Class element)
716 {
717 return toAnnotationProvider(element);
718 }
719
720 };
721
722
723
724
725 public static AnnotationProvider toAnnotationProvider(final Class element)
726 {
727 return InternalCommonsUtils.toAnnotationProvider(element);
728 }
729
730
731
732
733 public static final Mapper<Method, AnnotationProvider> METHOD_TO_AP_MAPPER = new Mapper<Method, AnnotationProvider>()
734 {
735 @Override
736 public AnnotationProvider map(final Method element)
737 {
738 return toAnnotationProvider(element);
739 }
740 };
741
742 public static final Method findMethod(Class containingClass, String methodName, Class... parameterTypes)
743 {
744 if (containingClass == null)
745 return null;
746
747 try
748 {
749 return containingClass.getMethod(methodName, parameterTypes);
750 } catch (SecurityException ex)
751 {
752 throw new RuntimeException(ex);
753 } catch (NoSuchMethodException ex)
754 {
755 return null;
756 }
757 }
758
759
760
761
762 public static ServiceDef3 toServiceDef3(ServiceDef sd)
763 {
764 if (sd instanceof ServiceDef3)
765 return (ServiceDef3) sd;
766
767 final ServiceDef2 sd2 = toServiceDef2(sd);
768
769 return new ServiceDef3()
770 {
771
772
773 @Override
774 public AnnotationProvider getClassAnnotationProvider()
775 {
776 return toAnnotationProvider(getServiceInterface());
777 }
778
779 @Override
780 public AnnotationProvider getMethodAnnotationProvider(final String methodName, final Class... argumentTypes)
781 {
782 return toAnnotationProvider(findMethod(getServiceInterface(), methodName, argumentTypes));
783 }
784
785 @Override
786 public Class getServiceImplementation()
787 {
788 return null;
789 }
790
791
792
793 @Override
794 public boolean isPreventDecoration()
795 {
796 return sd2.isPreventDecoration();
797 }
798
799 @Override
800 public ObjectCreator createServiceCreator(ServiceBuilderResources resources)
801 {
802 return sd2.createServiceCreator(resources);
803 }
804
805 @Override
806 public String getServiceId()
807 {
808 return sd2.getServiceId();
809 }
810
811 @Override
812 public Set<Class> getMarkers()
813 {
814 return sd2.getMarkers();
815 }
816
817 @Override
818 public Class getServiceInterface()
819 {
820 return sd2.getServiceInterface();
821 }
822
823 @Override
824 public String getServiceScope()
825 {
826 return sd2.getServiceScope();
827 }
828
829 @Override
830 public boolean isEagerLoad()
831 {
832 return sd2.isEagerLoad();
833 }
834
835 };
836 }
837
838 public static ServiceDef2 toServiceDef2(final ServiceDef sd)
839 {
840 if (sd instanceof ServiceDef2)
841 return (ServiceDef2) sd;
842
843 return new ServiceDef2()
844 {
845
846
847 @Override
848 public boolean isPreventDecoration()
849 {
850 return false;
851 }
852
853
854
855 @Override
856 public ObjectCreator createServiceCreator(ServiceBuilderResources resources)
857 {
858 return sd.createServiceCreator(resources);
859 }
860
861 @Override
862 public String getServiceId()
863 {
864 return sd.getServiceId();
865 }
866
867 @Override
868 public Set<Class> getMarkers()
869 {
870 return sd.getMarkers();
871 }
872
873 @Override
874 public Class getServiceInterface()
875 {
876 return sd.getServiceInterface();
877 }
878
879 @Override
880 public String getServiceScope()
881 {
882 return sd.getServiceScope();
883 }
884
885 @Override
886 public boolean isEagerLoad()
887 {
888 return sd.isEagerLoad();
889 }
890
891 @Override
892 public String toString()
893 {
894 return sd.toString();
895 }
896
897 @Override
898 public int hashCode()
899 {
900 final int prime = 31;
901 int result = 1;
902 result = prime * result + ((getServiceId() == null) ? 0 : getServiceId().hashCode());
903 return result;
904 }
905
906 @Override
907 public boolean equals(Object obj)
908 {
909 if (this == obj) { return true; }
910 if (obj == null) { return false; }
911 if (!(obj instanceof ServiceDefImpl)) { return false; }
912 ServiceDef other = (ServiceDef) obj;
913 if (getServiceId() == null)
914 {
915 if (other.getServiceId() != null) { return false; }
916 }
917 else if (!getServiceId().equals(other.getServiceId())) { return false; }
918 return true;
919 }
920
921 };
922 }
923
924 public static ModuleDef2 toModuleDef2(final ModuleDef md)
925 {
926 if (md instanceof ModuleDef2)
927 return (ModuleDef2) md;
928
929 return new ModuleDef2()
930 {
931 @Override
932 public Set<AdvisorDef> getAdvisorDefs()
933 {
934 return Collections.emptySet();
935 }
936
937 @Override
938 public Class getBuilderClass()
939 {
940 return md.getBuilderClass();
941 }
942
943 @Override
944 public Set<ContributionDef> getContributionDefs()
945 {
946 return md.getContributionDefs();
947 }
948
949 @Override
950 public Set<DecoratorDef> getDecoratorDefs()
951 {
952 return md.getDecoratorDefs();
953 }
954
955 @Override
956 public String getLoggerName()
957 {
958 return md.getLoggerName();
959 }
960
961 @Override
962 public ServiceDef getServiceDef(String serviceId)
963 {
964 return md.getServiceDef(serviceId);
965 }
966
967 @Override
968 public Set<String> getServiceIds()
969 {
970 return md.getServiceIds();
971 }
972
973 @Override
974 public Set<StartupDef> getStartups()
975 {
976 return Collections.emptySet();
977 }
978 };
979 }
980
981
982
983
984 public static ServiceLifecycle2 toServiceLifecycle2(final ServiceLifecycle lifecycle)
985 {
986 if (lifecycle instanceof ServiceLifecycle2)
987 return (ServiceLifecycle2) lifecycle;
988
989 return new ServiceLifecycle2()
990 {
991 @Override
992 public boolean requiresProxy()
993 {
994 return true;
995 }
996
997 @Override
998 public Object createService(ServiceResources resources, ObjectCreator creator)
999 {
1000 return lifecycle.createService(resources, creator);
1001 }
1002
1003 @Override
1004 public boolean isSingleton()
1005 {
1006 return lifecycle.isSingleton();
1007 }
1008 };
1009 }
1010
1011
1012
1013
1014 public static <T extends Comparable<T>> List<T> matchAndSort(Collection<? extends T> collection,
1015 Predicate<T> predicate)
1016 {
1017 assert predicate != null;
1018
1019 List<T> result = CollectionFactory.newList();
1020
1021 for (T object : collection)
1022 {
1023 if (predicate.accept(object))
1024 result.add(object);
1025 }
1026
1027 Collections.sort(result);
1028
1029 return result;
1030 }
1031
1032
1033
1034
1035 public static ContributionDef2 toContributionDef2(final ContributionDef contribution)
1036 {
1037 if (contribution instanceof ContributionDef2)
1038 return (ContributionDef2) contribution;
1039
1040 return new ContributionDef2()
1041 {
1042
1043 @Override
1044 public Set<Class> getMarkers()
1045 {
1046 return Collections.emptySet();
1047 }
1048
1049 @Override
1050 public Class getServiceInterface()
1051 {
1052 return null;
1053 }
1054
1055 @Override
1056 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources,
1057 Configuration configuration)
1058 {
1059 contribution.contribute(moduleSource, resources, configuration);
1060 }
1061
1062 @Override
1063 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources,
1064 OrderedConfiguration configuration)
1065 {
1066 contribution.contribute(moduleSource, resources, configuration);
1067 }
1068
1069 @Override
1070 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources,
1071 MappedConfiguration configuration)
1072 {
1073 contribution.contribute(moduleSource, resources, configuration);
1074 }
1075
1076 @Override
1077 public String getServiceId()
1078 {
1079 return contribution.getServiceId();
1080 }
1081
1082 @Override
1083 public String toString()
1084 {
1085 return contribution.toString();
1086 }
1087 };
1088 }
1089
1090 public static ContributionDef3 toContributionDef3(ContributionDef contribution)
1091 {
1092
1093 if (contribution instanceof ContributionDef2)
1094 {
1095 return (ContributionDef3) contribution;
1096 }
1097
1098 final ContributionDef2 cd2 = toContributionDef2(contribution);
1099
1100 return new ContributionDef3()
1101 {
1102 @Override
1103 public boolean isOptional()
1104 {
1105 return false;
1106 }
1107
1108 @Override
1109 public String getServiceId()
1110 {
1111 return cd2.getServiceId();
1112 }
1113
1114 @Override
1115 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources, Configuration configuration)
1116 {
1117 cd2.contribute(moduleSource, resources, configuration);
1118 }
1119
1120 @Override
1121 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources, OrderedConfiguration configuration)
1122 {
1123 cd2.contribute(moduleSource, resources, configuration);
1124 }
1125
1126 @Override
1127 public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources, MappedConfiguration configuration)
1128 {
1129 cd2.contribute(moduleSource, resources, configuration);
1130 }
1131
1132 @Override
1133 public Set<Class> getMarkers()
1134 {
1135 return cd2.getMarkers();
1136 }
1137
1138 @Override
1139 public Class getServiceInterface()
1140 {
1141 return cd2.getServiceInterface();
1142 }
1143
1144 @Override
1145 public String toString()
1146 {
1147 return cd2.toString();
1148 }
1149 };
1150 }
1151
1152
1153
1154
1155 public static AdvisorDef2 toAdvisorDef2(final AdvisorDef advisor)
1156 {
1157 if (advisor instanceof AdvisorDef2)
1158 return (AdvisorDef2) advisor;
1159
1160 return new AdvisorDef2()
1161 {
1162
1163 @Override
1164 public ServiceAdvisor createAdvisor(ModuleBuilderSource moduleSource, ServiceResources resources)
1165 {
1166 return advisor.createAdvisor(moduleSource, resources);
1167 }
1168
1169 @Override
1170 public String getAdvisorId()
1171 {
1172 return advisor.getAdvisorId();
1173 }
1174
1175 @Override
1176 public String[] getConstraints()
1177 {
1178 return advisor.getConstraints();
1179 }
1180
1181 @Override
1182 public boolean matches(ServiceDef serviceDef)
1183 {
1184 return advisor.matches(serviceDef);
1185 }
1186
1187 @Override
1188 public Set<Class> getMarkers()
1189 {
1190 return Collections.emptySet();
1191 }
1192
1193 @Override
1194 public Class getServiceInterface()
1195 {
1196 return null;
1197 }
1198
1199 @Override
1200 public String toString()
1201 {
1202 return advisor.toString();
1203 }
1204 };
1205 }
1206
1207
1208
1209
1210 public static DecoratorDef2 toDecoratorDef2(final DecoratorDef decorator)
1211 {
1212 if (decorator instanceof DecoratorDef2)
1213 return (DecoratorDef2) decorator;
1214
1215 return new DecoratorDef2()
1216 {
1217
1218 @Override
1219 public ServiceDecorator createDecorator(ModuleBuilderSource moduleSource, ServiceResources resources)
1220 {
1221 return decorator.createDecorator(moduleSource, resources);
1222 }
1223
1224 @Override
1225 public String[] getConstraints()
1226 {
1227 return decorator.getConstraints();
1228 }
1229
1230 @Override
1231 public String getDecoratorId()
1232 {
1233 return decorator.getDecoratorId();
1234 }
1235
1236 @Override
1237 public boolean matches(ServiceDef serviceDef)
1238 {
1239 return decorator.matches(serviceDef);
1240 }
1241
1242 @Override
1243 public Set<Class> getMarkers()
1244 {
1245 return Collections.emptySet();
1246 }
1247
1248 @Override
1249 public Class getServiceInterface()
1250 {
1251 return null;
1252 }
1253
1254 @Override
1255 public String toString()
1256 {
1257 return decorator.toString();
1258 }
1259 };
1260 }
1261
1262
1263
1264
1265
1266
1267
1268
1269 public static boolean isLocalFile(Class clazz)
1270 {
1271 String path = PlasticInternalUtils.toClassPath(clazz.getName());
1272
1273 ClassLoader loader = clazz.getClassLoader();
1274
1275
1276
1277 if (loader == null)
1278 return false;
1279
1280 URL classFileURL = loader.getResource(path);
1281
1282 return classFileURL != null && classFileURL.getProtocol().equals("file");
1283 }
1284
1285
1286
1287
1288
1289
1290 public static <S, T> Mapper<S, T> toMapper(final Coercion<S, T> coercion)
1291 {
1292 assert coercion != null;
1293
1294 return new Mapper<S, T>()
1295 {
1296 @Override
1297 public T map(S value)
1298 {
1299 return coercion.coerce(value);
1300 }
1301 };
1302 }
1303
1304 private static final AtomicLong uuidGenerator = new AtomicLong(System.nanoTime());
1305
1306
1307
1308
1309
1310
1311
1312 public static long nextUUID()
1313 {
1314 return uuidGenerator.incrementAndGet();
1315 }
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327 public static String getServiceId(AnnotatedElement annotated)
1328 {
1329 ServiceId serviceIdAnnotation = annotated.getAnnotation(ServiceId.class);
1330
1331 if (serviceIdAnnotation != null)
1332 {
1333 return serviceIdAnnotation.value();
1334 }
1335
1336 Named namedAnnotation = annotated.getAnnotation(Named.class);
1337
1338 if (namedAnnotation != null)
1339 {
1340 String value = namedAnnotation.value();
1341
1342 if (InternalCommonsUtils.isNonBlank(value))
1343 {
1344 return value;
1345 }
1346 }
1347
1348 return null;
1349 }
1350
1351
1352 public static AnnotationProvider toAnnotationProvider(final Method element)
1353 {
1354 return InternalCommonsUtils.toAnnotationProvider(element);
1355 }
1356
1357 public static <T> ObjectCreator<T> createConstructorConstructionPlan(final OperationTracker tracker, final ObjectLocator locator,
1358 final InjectionResources resources,
1359 final Logger logger,
1360 final String description,
1361 final Constructor<T> constructor)
1362 {
1363 return tracker.invoke(String.format("Creating plan to instantiate %s via %s",
1364 constructor.getDeclaringClass().getName(),
1365 constructor), new Invokable<ObjectCreator<T>>()
1366 {
1367 @Override
1368 public ObjectCreator<T> invoke()
1369 {
1370 validateConstructorForAutobuild(constructor);
1371
1372 ObjectCreator[] constructorParameters = calculateParameters(locator, resources, constructor.getParameterTypes(), constructor.getGenericParameterTypes(), constructor.getParameterAnnotations(), tracker);
1373
1374 Invokable<T> core = new ConstructorInvoker<T>(constructor, constructorParameters);
1375
1376 Invokable<T> wrapped = logger == null ? core : new LoggingInvokableWrapper<T>(logger, description, core);
1377
1378 ConstructionPlan<T> plan = new ConstructionPlan(tracker, description, wrapped);
1379
1380 extendPlanForInjectedFields(plan, tracker, locator, resources, constructor.getDeclaringClass());
1381
1382 extendPlanForPostInjectionMethods(plan, tracker, locator, resources, constructor.getDeclaringClass());
1383
1384 return plan;
1385 }
1386 });
1387 }
1388
1389 private static <T> void extendPlanForInjectedFields(final ConstructionPlan<T> plan, OperationTracker tracker, final ObjectLocator locator, final InjectionResources resources, Class<T> instantiatedClass)
1390 {
1391 Class clazz = instantiatedClass;
1392
1393 while (clazz != Object.class)
1394 {
1395 Field[] fields = clazz.getDeclaredFields();
1396
1397 for (final Field f : fields)
1398 {
1399
1400
1401 int fieldModifiers = f.getModifiers();
1402
1403 if (Modifier.isStatic(fieldModifiers) || Modifier.isFinal(fieldModifiers))
1404 continue;
1405
1406 final AnnotationProvider ap = new AnnotationProvider()
1407 {
1408 @Override
1409 public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
1410 {
1411 return f.getAnnotation(annotationClass);
1412 }
1413 };
1414
1415 String description = String.format("Calculating possible injection value for field %s.%s (%s)",
1416 clazz.getName(), f.getName(),
1417 PlasticUtils.toTypeName(f.getType()));
1418
1419 tracker.run(description, new Runnable()
1420 {
1421 @Override
1422 public void run()
1423 {
1424 final Class<?> fieldType = f.getType();
1425
1426 InjectService is = ap.getAnnotation(InjectService.class);
1427 if (is != null)
1428 {
1429 addInjectPlan(plan, f, locator.getService(is.value(), fieldType));
1430 return;
1431 }
1432
1433 if (ap.getAnnotation(Inject.class) != null || ap.getAnnotation(InjectResource.class) != null)
1434 {
1435 Object value = resources.findResource(fieldType, f.getGenericType());
1436
1437 if (value != null)
1438 {
1439 addInjectPlan(plan, f, value);
1440 return;
1441 }
1442
1443 addInjectPlan(plan, f, locator.getObject(fieldType, ap));
1444 return;
1445 }
1446
1447 if (ap.getAnnotation(javax.inject.Inject.class) != null)
1448 {
1449 Named named = ap.getAnnotation(Named.class);
1450
1451 if (named == null)
1452 {
1453 addInjectPlan(plan, f, locator.getObject(fieldType, ap));
1454 } else
1455 {
1456 addInjectPlan(plan, f, locator.getService(named.value(), fieldType));
1457 }
1458
1459 return;
1460 }
1461
1462
1463
1464 }
1465 });
1466 }
1467
1468 clazz = clazz.getSuperclass();
1469 }
1470 }
1471
1472 private static <T> void addInjectPlan(ConstructionPlan<T> plan, final Field field, final Object injectedValue)
1473 {
1474 plan.add(new InitializationPlan<T>()
1475 {
1476 @Override
1477 public String getDescription()
1478 {
1479 return String.format("Injecting %s into field %s of class %s.",
1480 injectedValue,
1481 field.getName(),
1482 field.getDeclaringClass().getName());
1483 }
1484
1485 @Override
1486 public void initialize(T instance)
1487 {
1488 inject(instance, field, injectedValue);
1489 }
1490 });
1491 }
1492
1493 private static boolean hasAnnotation(AccessibleObject member, Class<? extends Annotation> annotationType)
1494 {
1495 return member.getAnnotation(annotationType) != null;
1496 }
1497
1498 private static <T> void extendPlanForPostInjectionMethods(ConstructionPlan<T> plan, OperationTracker tracker, ObjectLocator locator, InjectionResources resources, Class<T> instantiatedClass)
1499 {
1500 for (Method m : instantiatedClass.getMethods())
1501 {
1502 if (hasAnnotation(m, PostInjection.class) || hasAnnotation(m, PostConstruct.class))
1503 {
1504 extendPlanForPostInjectionMethod(plan, tracker, locator, resources, m);
1505 }
1506 }
1507 }
1508
1509 private static void extendPlanForPostInjectionMethod(final ConstructionPlan<?> plan, final OperationTracker tracker, final ObjectLocator locator, final InjectionResources resources, final Method method)
1510 {
1511 tracker.run("Computing parameters for post-injection method " + method,
1512 new Runnable()
1513 {
1514 @Override
1515 public void run()
1516 {
1517 final ObjectCreator[] parameters = calculateParametersForMethod(method, locator,
1518 resources, tracker);
1519
1520 plan.add(new InitializationPlan<Object>()
1521 {
1522 @Override
1523 public String getDescription()
1524 {
1525 return "Invoking " + method;
1526 }
1527
1528 @Override
1529 public void initialize(Object instance)
1530 {
1531 Throwable fail = null;
1532
1533 Object[] realized = realizeObjects(parameters);
1534
1535 try
1536 {
1537 method.invoke(instance, realized);
1538 } catch (InvocationTargetException ex)
1539 {
1540 fail = ex.getTargetException();
1541 } catch (Exception ex)
1542 {
1543 fail = ex;
1544 }
1545
1546 if (fail != null)
1547 {
1548 throw new RuntimeException(String
1549 .format("Exception invoking method %s: %s", method, ExceptionUtils.toMessage(fail)), fail);
1550 }
1551 }
1552 });
1553 }
1554 });
1555 }
1556
1557
1558 public static <T> ObjectCreator<T> createMethodInvocationPlan(final OperationTracker tracker, final ObjectLocator locator,
1559 final InjectionResources resources,
1560 final Logger logger,
1561 final String description,
1562 final Object instance,
1563 final Method method)
1564 {
1565
1566 return tracker.invoke("Creating plan to invoke " + method, new Invokable<ObjectCreator<T>>()
1567 {
1568 @Override
1569 public ObjectCreator<T> invoke()
1570 {
1571 ObjectCreator[] methodParameters = calculateParametersForMethod(method, locator, resources, tracker);
1572
1573 Invokable<T> core = new MethodInvoker<T>(instance, method, methodParameters);
1574
1575 Invokable<T> wrapped = logger == null ? core : new LoggingInvokableWrapper<T>(logger, description, core);
1576
1577 return new ConstructionPlan(tracker, description, wrapped);
1578 }
1579 });
1580 }
1581
1582
1583
1584
1585 public final static Mapper<ObjectCreator, Object> CREATE_OBJECT = new Mapper<ObjectCreator, Object>()
1586 {
1587 @Override
1588 public Object map(ObjectCreator element)
1589 {
1590 return element.createObject();
1591 }
1592 };
1593
1594
1595
1596
1597 public static Object[] realizeObjects(ObjectCreator[] creators)
1598 {
1599 return F.flow(creators).map(CREATE_OBJECT).toArray(Object.class);
1600 }
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610 public static List<String> sortedKeys(Map map)
1611 {
1612 return InternalCommonsUtils.sortedKeys(map);
1613 }
1614
1615
1616
1617
1618
1619
1620 public static String toUserPresentable(String id)
1621 {
1622 return InternalCommonsUtils.toUserPresentable(id);
1623 }
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633 public static String extractIdFromPropertyExpression(String expression)
1634 {
1635 return InternalCommonsUtils.extractIdFromPropertyExpression(expression);
1636 }
1637
1638
1639
1640
1641
1642 public static String defaultLabel(String id, Messages messages, String propertyExpression)
1643 {
1644 return InternalCommonsUtils.defaultLabel(id, messages, propertyExpression);
1645 }
1646
1647 public static String replace(String input, Pattern pattern, String replacement)
1648 {
1649 return InternalCommonsUtils.replace(input, pattern, replacement);
1650 }
1651
1652 }